#! /usr/bin/ruby
class Data_Interpolation


	def initialize

		data = { :pressure=>[],:height=>[],:temp=>[],:dew_point=>[],:wind_dir=>[],:wind_speed=>[] }
		# = { :pressure=>[],:height=>[],:temp=>[],:dew_point=>[],:wind_speed=>[],:wind_dir=>[] }
		interpolated_lagrange = { :pressure=>[],:height=>[],:temp=>[],:dew_point=>[],:wind_speed=>[],:wind_dir=>[] }
		header_length = 14

		text_file="balloon_sounding.txt"
		lines = File.open(text_file, "r").readlines

		lines[header_length..-1].each do |line|
			l = line.split(" ")
			data[:pressure] << l[0].to_i
			data[:height] << l[1].to_i
			data[:temp] << l[2].to_i
			data[:dew_point] << l[3].to_i
			data[:wind_dir] << l[4].to_i
			data[:wind_speed] << l[5].to_i
		end
		

		
		#data.each_pair { |key,value| data[:key] = build_linear(value) }
		
		data.each_pair { |key,value| interpolated_lagrange[:key] = build_lagrange(value) }
		p data[:temp]

		#write_data(data,"linear_interp")
		
		for i in 0...data[:wind_dir].length
			if  data[:wind_dir][i] < 0 || data[:wind_dir][i] >360
				if (data[:wind_dir][i]) < 0
					data[:wind_dir][i] = data[:wind_dir][i]-360*(data[:wind_dir][i].to_f/360.0).floor
				elsif (data[:wind_dir][i]) > 360
					data[:wind_dir][i] = data[:wind_dir][i]-360*(data[:wind_dir][i].to_f/360.0).floor
				end
			end
		end
		
		for i in 0...data[:wind_speed].length
			data[:wind_speed][i] = data[:wind_speed][i].abs
		end

		write_data(data,"lagrange_interp")
	end
	
	def interp_write(data,method)
	end
	
	
	def build_linear(data)

		nil_val=99999
		data_length = data.length-1
		x_nil= Array.new
		
		for i in 0...data.length
			if data[i] == nil_val
				x_nil << i
			end
		end

		x_good=Array.new(data.length) { |i| i }
		x_good = x_good-x_nil

		if data[0] == nil_val
			data[0] = linear_approx(data[x_good[0]],data[x_good[1]],x_good[0],x_good[1],0)
			x_good.insert(0,0)
		end

		if data[-1] == nil_val
			data[-1] = linear_approx(data[x_good[-2]],data[x_good[-1]],x_good[-2],x_good[-1],data_length)
			x_good << data_length
		end

		x_nil.each do |find_nil|
			for i in 0...x_good.length
				if x_good[i] < find_nil
					data[find_nil] = linear_approx(data[x_good[i]],data[x_good[i+1]],x_good[i],x_good[i+1],find_nil) unless x_good[i+1] == nil
				end
			end					
			x_good << find_nil
			x_good.uniq!
			x_good.sort!
		end
		return data
	end

	def linear_approx(val_initial,val_final,x_i,x_f,x)
		return ((val_final-val_initial)/(x_f-x_i))*(x-x_i)+val_initial
	end

	def build_lagrange(data)
		nil_val=99999
		data_length = data.length-1
		x_nil= Array.new
		
		for i in 0...data.length
			if data[i] == nil_val
				x_nil << i
			end
		end
		
		x_good=Array.new(data.length) { |i| i }
		x_good=x_good-x_nil
		
		if data[0] == nil_val
			data[0] = linear_approx(data[x_good[0]],data[x_good[1]],x_good[0],x_good[1],0)
			x_good.insert(0,0)
		end
		
		if data[-1] == nil_val
			data[-1] = linear_approx(data[x_good[-2]],data[x_good[-1]],x_good[-2],x_good[-1],data_length)
			x_good << data_length
		end

		x_nil.each do |find_nil|
			for i in 0...x_good.length
				if x_good[i-2] < find_nil
					data[find_nil] = lagrange_approx(data,x_good[i-2..i+2],find_nil).to_i unless x_good[i+2] == nil || x_good[i-2]==nil
				end
			end	
			#data[find_nil] = lagrange_approx(data,x_good,find_nil).to_f
			x_good << find_nil
			x_good.uniq!
			x_good.sort!
		end
		return data
	end

	def lagrange_approx(data,x_good,x_nil,k=0)
		if k<x_good.length
			return p_of_k(data,x_good,x_nil,k).to_f*data[x_good[k]].to_f + lagrange_approx(data,x_good,x_nil,k+1).to_f
		else
			return 0
		end
	end

	def p_of_k(data,x_good,x_nil,k,i=0)
		if k==i
			return p_of_k(data,x_good,x_nil,k,i+1).to_f
		elsif i<x_good.length
			return ((x_nil.to_f-x_good[i].to_f)/(x_good[k].to_f-x_good[i].to_f))*p_of_k(data,x_good,x_nil,k,i+1).to_f
		else
			return 1.0
		end
	end

	def write_data(data,file)
		file = File.new("#{file}.txt","w+")
		file.puts("Column 1 = Pressure\nColumn 2 = Height\nColumn 3 = Temp\nColumn 4 = Dew-Point\nColumn 5 = Wind-Dir\nColumn 6 = Wind-Speed")
		file.puts("----------------------------------------------")
		
		for i in 0...data[:pressure].length
			file << "#{data[:pressure][i]}\t#{data[:height][i]}\t#{data[:temp][i]}\t#{data[:dew_point][i]}\t#{data[:wind_dir][i]}\t#{data[:wind_speed][i]}"
			file << "\n"
		end
	end

end			

Data_Interpolation.new
